
package com.hlkj.pay.controller.merchant;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.pojo.LocalContext;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.pay.app.merchant.IAgentInfoAppService;
import com.hlkj.pay.app.merchant.IMerchantInfoAppService;
import com.hlkj.pay.app.transfer.PayChannelDoToResp;
import com.hlkj.pay.app.transfer.ProviderDoToResp;
import com.hlkj.pay.controller.BaseController;
import com.hlkj.pay.dto.LocalAdminUserRequest;
import com.hlkj.pay.dto.merchant.MerchantInfoDto;
import com.hlkj.pay.dto.merchant.MerchantInfoQueryDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.finance.MerchantAmountDO;
import com.hlkj.pay.infrastructure.model.merchant.AgentInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderInfoDO;
import com.hlkj.pay.service.merchant.IAgentService;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.service.pay.IProviderService;
import com.hlkj.pay.vo.merchant.req.agent.AgentInfoAddReq;
import com.hlkj.pay.vo.merchant.req.agent.AgentInfoUpdateReq;
import com.hlkj.pay.vo.merchant.req.agent.AgentPageReq;
import com.hlkj.pay.vo.merchant.req.info.MerchantFeeConfigReq;
import com.hlkj.pay.vo.merchant.req.info.UpdateMerchantStatusReq;
import com.hlkj.pay.vo.merchant.resp.agent.AgentInfoDetailResp;
import com.hlkj.pay.vo.merchant.resp.agent.AgentInfoPageResp;
import com.hlkj.pay.vo.merchant.resp.info.MerchantFeeConfigResp;

import cn.hutool.core.bean.BeanUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

/**
 * @author HlpayTeam
 * @date 2024/09/12 11:32
 */
@Tag(name = "代理商配置")
@RestController
@RequestMapping("/v1/agent/info")
@RequiredArgsConstructor
public class AgentController extends BaseController {

    private final IAgentInfoAppService agentInfoAppService;

    private final IMerchantService merchantService;
    private final IMerchantConfigService merchantConfigService;

    private final IAgentService agentService;

    private final IProviderService providerService;

    private final IPayChannelService payChannelService;

    private final IMerchantInfoAppService merchantInfoAppService;


    @Operation(summary = "代理商列表分页")
    @GetMapping("/page")
    CommonResult<PageResult<AgentInfoPageResp>> queryPage(@Validated AgentPageReq agentPageReq) {
        MerchantInfoQueryDto merchantInfoQueryDto = new MerchantInfoQueryDto();
        merchantInfoQueryDto.setLikeName(agentPageReq.getName());
        merchantInfoQueryDto.setLikeAccount(agentPageReq.getAccount());
        merchantInfoQueryDto.setLikeLegalPhone(agentPageReq.getLegalPhone());
        merchantInfoQueryDto.setLikeSuperAgent(agentPageReq.getSuperAgent());
        merchantInfoQueryDto.setStatus(agentPageReq.getStatus());
        merchantInfoQueryDto.setSignStatus(agentPageReq.getSignStatus());
        merchantInfoQueryDto.setPageNo(agentPageReq.getPageNo());
        merchantInfoQueryDto.setPageSize(agentPageReq.getPageSize());
        merchantInfoQueryDto.setSn(agentPageReq.getSn());
        merchantInfoQueryDto.setSnType(MerchantEnum.MERCHANT_SN_TYPE.AGENT.getCode());
        PageResult<MerchantInfoDto> page = merchantService.queryPage(merchantInfoQueryDto);
        List<MerchantInfoDto> list = page.getList();
        if (CollectionUtils.isEmpty(list)) {
            return buildPageResult(page, Collections.emptyList());
        }
        List<AgentInfoPageResp> agentInfoPageResps = BeanUtil.copyToList(list, AgentInfoPageResp.class);
        List<String> superAgentList = agentInfoPageResps.stream().map(merchantInfoPageResp -> merchantInfoPageResp.getSuperAgent()).collect(Collectors.toList());
        List<String> snList = agentInfoPageResps.stream().map(merchantInfoPageResp -> merchantInfoPageResp.getSn()).collect(Collectors.toList());
        Map<String, MerchantInfoDO> merchantInfoDOMap = new HashMap<>();
        Map<String, ProviderInfoDO> providerInfoMap = new HashMap<>();
        Map<String, List<String>> providerCodeMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(superAgentList)) {
            merchantInfoQueryDto = new MerchantInfoQueryDto();
            merchantInfoQueryDto.setSnList(superAgentList);
            List<MerchantInfoDO> merchantInfoList = merchantService.queryList(merchantInfoQueryDto);
            merchantInfoDOMap = merchantInfoList.stream().collect(Collectors.toMap(MerchantInfoDO::getSn, Function.identity(), (t1, t2) -> t1));
        }
        List<MerchantConfigDO> merchantConfigList = merchantConfigService.queryConfig(snList);
        if (!CollectionUtils.isEmpty(merchantConfigList)) {
            List<String> providerCodeList = new ArrayList<>();
            merchantConfigList.stream().forEach(merchantConfigDO -> {
                providerCodeList.addAll(merchantConfigDO.getProviderCodeList());
                providerCodeMap.put(merchantConfigDO.getSn(), merchantConfigDO.getProviderCodeList());

            });
            List<ProviderInfoDO> providerInfoList = providerService.queryByCodes(providerCodeList);
            providerInfoMap = providerInfoList.stream().collect(Collectors.toMap(ProviderInfoDO::getCode, Function.identity(), (t1, t2) -> t1));
        }
        Map<String, ProviderInfoDO> finalProviderInfoMap = providerInfoMap;
        for (AgentInfoPageResp agentInfoPageResp : agentInfoPageResps) {
            MerchantInfoDO merchantInfoDO = merchantInfoDOMap.get(agentInfoPageResp.getSuperAgent());
            if (merchantInfoDO != null) {
                agentInfoPageResp.setSuperAgentName(merchantInfoDO.getName());
            }
            List<String> providerCodeList = providerCodeMap.get(agentInfoPageResp.getSn());
            if (!CollectionUtils.isEmpty(providerCodeList)) {
                providerCodeList.stream().forEach(providerCode -> {
                    agentInfoPageResp.getProviderInfoList().add(ProviderDoToResp.INSTANCE.providerInfoResp(finalProviderInfoMap.get(providerCode)));
                });
            }
        }
        return buildPageResult(page, agentInfoPageResps);
    }

    @Operation(summary = "代理商列表不分页")
    @GetMapping("")
    CommonResult<List<AgentInfoPageResp>> queryList(@Validated AgentPageReq agentPageReq) {
        MerchantInfoQueryDto merchantInfoQueryDto = new MerchantInfoQueryDto();
        merchantInfoQueryDto.setLikeName(agentPageReq.getName());
        merchantInfoQueryDto.setLikeAccount(agentPageReq.getAccount());
        merchantInfoQueryDto.setLikeLegalPhone(agentPageReq.getLegalPhone());
        merchantInfoQueryDto.setLikeSuperAgent(agentPageReq.getSuperAgent());
        merchantInfoQueryDto.setStatus(agentPageReq.getStatus());
        merchantInfoQueryDto.setSignStatus(agentPageReq.getSignStatus());
        merchantInfoQueryDto.setSnType(MerchantEnum.MERCHANT_SN_TYPE.AGENT.getCode());
        List<MerchantInfoDO> list = merchantService.queryList(merchantInfoQueryDto);
        if (CollectionUtils.isEmpty(list)) {
            return CommonResult.success(Collections.emptyList());
        }
        return CommonResult.success(BeanUtil.copyToList(list, AgentInfoPageResp.class));
    }

    @Operation(summary = "代理商详情")
    @GetMapping("/detail")
    CommonResult<AgentInfoDetailResp> detail(@RequestParam(value = "sn", required = false) String sn) {
        // 商户平台没有传sn
        if (!StringUtils.hasText(sn)) {
            LocalAdminUserRequest localAdminUserRequest = (LocalAdminUserRequest) LocalContext.get();
            sn = localAdminUserRequest.getSn();
        }
        MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(sn);
        if (merchantInfoDO == null) {
            return CommonResult.success();
        }
        AgentInfoDO agentInfoDO = agentService.queryAgent(sn);
        MerchantAmountDO merchantAmountDO = merchantService.queryMerchantAmount(sn);
        AgentInfoDetailResp agentInfoDetailResp = BeanUtil.copyProperties(agentInfoDO, AgentInfoDetailResp.class);
        BeanUtil.copyProperties(merchantInfoDO, agentInfoDetailResp);
        // 金额信息复制
        BeanUtil.copyProperties(merchantAmountDO, agentInfoDetailResp);

        MerchantConfigDO merchantConfigDO = merchantInfoAppService.queryConfig(sn);
        if (merchantConfigDO != null) {
            agentInfoDetailResp.setProviderCodeList(merchantConfigDO.getProviderCodeList());
            agentInfoDetailResp.setChannelCodeList(merchantConfigDO.getChannelCodeList());
            if (!CollectionUtils.isEmpty(merchantConfigDO.getProviderCodeList())) {
                List<ProviderInfoDO> providerInfoList = providerService.queryByCodes(merchantConfigDO.getProviderCodeList());
                agentInfoDetailResp.setProviderList(ProviderDoToResp.INSTANCE.providerInfoRespList(providerInfoList));
            }
            if (!CollectionUtils.isEmpty(merchantConfigDO.getChannelCodeList())) {
                List<PayChannelDO> payChannelList = payChannelService.queryByCodes(merchantConfigDO.getChannelCodeList());
                agentInfoDetailResp.setChannelList(PayChannelDoToResp.INSTANCE.payChannelListRespList(payChannelList));
            }
        }
        if (agentInfoDO != null) {
            agentInfoDetailResp.setLowerAgentStatus(agentInfoDO.getLowerAgentStatus());
            agentInfoDetailResp.setLowerMerchantStatus(agentInfoDO.getLowerMerchantStatus());
            agentInfoDetailResp.setProfitRate(agentInfoDO.getProfitRate());
            agentInfoDetailResp.setOpenStatus(agentInfoDO.getOpenStatus());
            agentInfoDetailResp.setPasswordType(agentInfoDO.getPasswordType());
            agentInfoDetailResp.setPassword(agentInfoDO.getPassword());
            agentInfoDetailResp.setSettleCardFrontUrl(agentInfoDO.getSettleCardFrontUrl());
            agentInfoDetailResp.setAccountType(agentInfoDO.getAccountType());
            agentInfoDetailResp.setCardNo(agentInfoDO.getCardNo());
            agentInfoDetailResp.setBankName(agentInfoDO.getBankName());
            agentInfoDetailResp.setBranchName(agentInfoDO.getBranchName());
            agentInfoDetailResp.setBranchCode(agentInfoDO.getBranchCode());
            agentInfoDetailResp.setBankAreaName(agentInfoDO.getBankAreaName());
            agentInfoDetailResp.setLowerAgentStatus(agentInfoDO.getLowerAgentStatus());
            agentInfoDetailResp.setLowerMerchantStatus(agentInfoDO.getLowerMerchantStatus());
            agentInfoDetailResp.setBlockBal(agentInfoDO.getBlockBal());
        }
        return CommonResult.success(agentInfoDetailResp);
    }

    @Operation(summary = "删除代理商")
    @DeleteMapping("")
    CommonResult<Void> delMerchant(@Validated @RequestBody UpdateMerchantStatusReq updateMerchantStatusReq) {
        return agentInfoAppService.delAgent(updateMerchantStatusReq.getSn());
    }

    @Operation(summary = "更新代理商信息")
    @PutMapping("")
    CommonResult<Void> updateMerchantInfo(@Validated @RequestBody AgentInfoUpdateReq agentInfoUpdateReq) {
        return agentInfoAppService.updateAgent(agentInfoUpdateReq);
    }

    @Operation(summary = "新增代理商")
    @PostMapping("")
    CommonResult<String> addAgentInfo(@Validated @RequestBody AgentInfoAddReq agentInfoAddReq) {
        return agentInfoAppService.addAgentInfo(agentInfoAddReq);
    }

    @Operation(summary = "更新代理商状态")
    @PostMapping("/status")
    CommonResult<Void> updateStatus(@Validated @RequestBody UpdateMerchantStatusReq updateStatusReq) {
        return merchantInfoAppService.updateStatus(updateStatusReq);
    }

    @Operation(summary = "更新代理商交易状态")
    @PostMapping("/status/tran")
    CommonResult<Void> updateTranStatus(@Validated @RequestBody UpdateMerchantStatusReq updateStatusReq) {
        return merchantInfoAppService.updateTranStatus(updateStatusReq);
    }

    @Operation(summary = "获取代理商费率配置")
    @GetMapping("/feeConfig")
    CommonResult<List<MerchantFeeConfigResp>> queryProviderFeeConfig(@RequestParam(name = "sn") String sn) {
        return merchantInfoAppService.queryFeeConfig(sn);
    }

    @Operation(summary = "保存代理商费率配置")
    @PostMapping("/feeConfig")
    CommonResult<Void> saveProviderFeeConfig(@Validated @RequestBody MerchantFeeConfigReq merchantFeeConfigReq) {
        return merchantInfoAppService.saveFeeConfig(merchantFeeConfigReq);
    }
}
